/*
 * MainFrame.cpp
 *
 *  Created on: Aug 25, 2011
 *      Author: erudhes
 */
#include <map>
#include <wx/tooltip.h>
#include <wx/filename.h>
#include "MainFrame.h"
#include "MainPanel.h"
#include "MessagingFrame.h"
#include "ServerRegistrationHandler.h"
#include "WxUtils.h"
#include "Configuration.h"
#include "App.h"

/**
 * |-------------------|---------|-----------|-----------|---------------|--------------|----------|------|------|
 * | States\Menupoints | Restart | Messaging | Configure | Start Hosting | Change level | Kisk-Off | Join | Host |
 * |-------------------|---------|-----------|-----------|---------------|--------------|----------|------|------|
 * | Idle              |    N    |     N     |     Y     |       Y       |      N       |    N     |   Y  |   Y  |
 * |-------------------|---------|-----------|-----------|---------------|--------------|----------|------|------|
 * | Starting          |    N    |     N     |     N     |       N       |      N       |    N     |   N  | N**  |
 * |-------------------|---------|-----------|-----------|---------------|--------------|----------|------|------|
 * | Started           |    Y    |     Y     |     N     |       N       |      Y       |    Y     |   N  | N**  |
 * |-------------------|---------|-----------|-----------|---------------|--------------|----------|------|------|
 * | Finished          |    Y    |     Y     |     N     |       N       |      Y       |    Y     |   N  | N**  |
 * |-------------------|---------|-----------|-----------|---------------|--------------|----------|------|------|
 *
 * ** Only on client side. On server side should remain available
 */

// Declare event handler methods
BEGIN_EVENT_TABLE(MainFrame, wxFrame)
EVT_MENU(MAIN_FRAME_MENU_NEW_HOST_START_HOSTING_ID, MainFrame::onMenuNewHostClicked)
EVT_MENU(MAIN_FRAME_MENU_NEW_HOST_CHANGE_LEVEL_ID, MainFrame::onMenuNewHostClicked)
EVT_MENU(MAIN_FRAME_MENU_NEW_HOST_KICK_OFF_CLIENT_ID, MainFrame::onMenuNewHostKickOffClicked)
EVT_MENU(MAIN_FRAME_MENU_NEW_JOIN_ID, MainFrame::onMenuNewJoinClicked)
EVT_MENU(MAIN_FRAME_MENU_RESTART_ID, MainFrame::onMenuRestartClicked)
EVT_MENU(MAIN_FRAME_MENU_CLOSE_ID, MainFrame::onMenuCloseClicked)
EVT_MENU(MAIN_FRAME_MENU_EXIT_ID, MainFrame::onMenuExitClicked)
EVT_MENU(MAIN_FRAME_MENU_CONFIGURE_ID, MainFrame::onMenuConfigureClicked)
EVT_MENU(MAIN_FRAME_MENU_MESSAGING_ID, MainFrame::onMenuMessagingClicked)
END_EVENT_TABLE()

/**
 * Here you can find the ugly GUI and menu builder code.
 * There is no more to comment on it, basically just creating and placing controllers to the right place.
 */

MainFrame::MainFrame(const wxString& title, long style): wxFrame(NULL, MAIN_FRAME_WIN_ID, title, wxDefaultPosition, wxDefaultSize, style),
                                                         mMainPanel(NULL), mStatusBar(NULL), mMessagingFrame(NULL), mIsServerStarting(false)
{
	wxMenu* fileMenu = new wxMenu();
	wxMenu* newSubMenu = new wxMenu();
	wxMenu* hostSubMenu = new wxMenu();
	wxMenu* configureMenu = new wxMenu();
	wxMenu* messagingMenu = new wxMenu();
	wxMenuBar* menuBar = new wxMenuBar();
	wxMenuItem* changeLevelMenuItem = NULL;
	wxMenuItem* kickOffClientMenuItem = NULL;
	wxMenuItem* restartMenuItem = NULL;
	wxMenuItem* messagingMenuItem = NULL;
	wxMenuItem* enablemessagingMenuItem = NULL;

	// Build up the menu
	hostSubMenu->Append(MAIN_FRAME_MENU_NEW_HOST_START_HOSTING_ID, wxT("Start Hosting"));
	changeLevelMenuItem = hostSubMenu->Append(MAIN_FRAME_MENU_NEW_HOST_CHANGE_LEVEL_ID, wxT("Change Level"));
	changeLevelMenuItem->Enable(false);
	kickOffClientMenuItem = hostSubMenu->Append(MAIN_FRAME_MENU_NEW_HOST_KICK_OFF_CLIENT_ID, wxT("Kick-Off Client"));
	kickOffClientMenuItem->Enable(false);
	newSubMenu->AppendSubMenu(hostSubMenu, wxT("Host"));
	newSubMenu->Append(MAIN_FRAME_MENU_NEW_JOIN_ID, wxT("Join"));
	fileMenu->AppendSubMenu(newSubMenu, wxT("New"));
	restartMenuItem = fileMenu->Append(MAIN_FRAME_MENU_RESTART_ID, wxT("Restart"));
	restartMenuItem->Enable(false);
	fileMenu->Append(MAIN_FRAME_MENU_CLOSE_ID, wxT("Close"));
	fileMenu->Append(MAIN_FRAME_MENU_EXIT_ID, wxT("Exit"));
	configureMenu->Append(MAIN_FRAME_MENU_CONFIGURE_ID, wxT("Configure..."));
	messagingMenuItem = messagingMenu->Append(MAIN_FRAME_MENU_MESSAGING_ID, wxT("Instant messaging..."));
	messagingMenuItem->Enable(false);
	enablemessagingMenuItem = messagingMenu->Append(MAIN_FRAME_MENU_ENABLE_MESSAGING_ID, wxT("Messaging enabled"), wxEmptyString, wxITEM_CHECK);
	enablemessagingMenuItem->Check(true);
	menuBar->Append(fileMenu, wxT("File"));
	menuBar->Append(configureMenu, wxT("Configure"));
	menuBar->Append(messagingMenu, wxT("Messaging"));
	this->SetMenuBar(menuBar);
	mMainPanel = new MainPanel(this);
	// Create the status bar
	mStatusBar = this->CreateStatusBar();
	mStatusBar->SetStatusText(wxT("Idle"));
	this->SetClientSize(this->GetClientSize().x, this->GetClientSize().y + 20);
	this->Center();
}

/*virtual*/
MainFrame::~MainFrame()
{
	// Nothing to do yet
}

void MainFrame::onMenuNewHostClicked(wxCommandEvent& /*menuEvent*/)
{
	const unsigned int panelHeight = 80;
	const unsigned int panelWidth = 80;
	wxChar pathSeparator = wxFileName::GetPathSeparator();
	wxString path = wxGetCwd() + pathSeparator + wxGetApp().getConfiguration()->getLevels()->getPath() + pathSeparator;
	wxString title(wxT("Choose a level"));
	wxDialog* levelDialog = new wxDialog(this, MAIN_FRAME_MENU_NEW_HOST_DIALOG_ID, title);
	wxSize dialogSize(panelWidth, panelHeight);
	unsigned int counter = 0;
	std::vector<wxString> levels = wxGetApp().getConfiguration()->getLevels()->getLevelNames();
	wxPanel* cancelPanel = NULL;
	wxButton* cancelButton = NULL;

	// We are going to start a server
	mIsServerStarting = true;
	// Build up the level selection dialog
	for(std::vector<wxString>::iterator iterator = levels.begin(); iterator != levels.end(); iterator++)
	{
		wxString bitmapPath = path + *iterator + pathSeparator + wxT("thumbnails.bmp");
		wxBitmap* bitmap = new wxBitmap(bitmapPath, wxBITMAP_TYPE_BMP);
		wxPanel* panel = new wxPanel(levelDialog, (counter % 5) * panelWidth, (counter / 5) * panelHeight, panelWidth, panelHeight);
		wxStaticBitmap* staticBitmap = new wxStaticBitmap(panel, wxID_ANY, *bitmap);
		wxButton* button = new wxButton(panel, wxID_ANY, wxT("Select"), wxPoint(0, 60), wxSize(panelWidth, 20));

		button->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainFrame::onClicked), NULL, this);
		button->SetToolTip(*iterator);
		button->SetClientData(levelDialog);
		staticBitmap->SetToolTip(*iterator);
		counter++;
	}
	// If no level show a "no level" thumbnail to the user
	if(0 == counter)
	{
		wxString bitmapPath = path + wxT("no_levels.bmp");
		wxBitmap* bitmap = new wxBitmap(bitmapPath, wxBITMAP_TYPE_BMP);
		wxPanel* panel = new wxPanel(levelDialog, 0, 0, panelWidth, panelHeight);
		wxStaticBitmap* staticBitmap = new wxStaticBitmap(panel, wxID_ANY, *bitmap);

		staticBitmap->SetToolTip(wxT("No server registered"));
	} // Else, calculate the dialog's size dynamically
	else if(5 == counter)
		dialogSize = wxSize(400, panelHeight);
	else if(1 <= (counter / 5))
		dialogSize = wxSize(400, ((counter / 5) + 1) * panelHeight);
	else
		dialogSize = wxSize((counter % 5) * panelWidth, panelHeight);
	dialogSize.y += 20;
	// Place the Cancel and the OK button
	cancelPanel = new wxPanel(levelDialog, MAIN_FRAME_JOIN_IP_PANEL_ID, wxPoint(0, dialogSize.y - 20), wxSize(dialogSize.x, 20));
	cancelButton = new wxButton(cancelPanel, MAIN_FRAME_HOST_CANCEL_BUTTON_ID, wxString(wxT("Cancel")), wxPoint(dialogSize.x / 2 - panelWidth / 2, 0), wxSize(panelWidth, 20));
	cancelButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainFrame::onClicked), NULL, this);
	cancelButton->SetClientData(levelDialog);
	// Set the data needed for later use when the user clicked on a button on the dialog
	levelDialog->SetClientData(NULL);
	levelDialog->SetClientSize(dialogSize);
	levelDialog->Show(true);
}

void MainFrame::onMenuNewHostKickOffClicked(wxCommandEvent& menuEvent)
{
	mMainPanel->kickOffClient();
}

void MainFrame::onMenuNewJoinClicked(wxCommandEvent& /*menuEvent*/)
{
	const unsigned int panelHeight = 80;
	const unsigned int panelWidth = 80;
	wxChar pathSeparator = wxFileName::GetPathSeparator();
	wxString path = wxGetCwd() + pathSeparator + wxGetApp().getConfiguration()->getLevels()->getPath() + pathSeparator;
	wxString title(wxT("Choose an available free server"));
	wxDialog* hostDialog = new wxDialog(this, MAIN_FRAME_MENU_NEW_JOIN_DIALOG_ID, title);
	std::map<wxString, JoiningData*>* joiningDatas = new std::map<wxString, JoiningData*>();
	wxSize dialogSize(400, panelHeight);
	wxSize defaultSize(100, 20);
	unsigned int counter = 0;
	std::vector<ServerRegistrationHandler::ServerInfo> response;
	wxPanel* ipPanel = NULL;
	wxButton* okButton = NULL;
	wxButton* cancelButton = NULL;

	// We are going to start a client
	mIsServerStarting = false;
	// Query the servers
	ServerRegistrationHandler::queryServers(wxGetApp().getConfiguration()->getNetworkConfiguration()->fetchOnlyFreeServers(),  response);
	// Create the server selection dialog
	for(std::vector<ServerRegistrationHandler::ServerInfo>::iterator iterator = response.begin(); iterator != response.end(); iterator++)
	{
		wxString bitmapPath;
		wxBitmap* bitmap = NULL;
		wxStaticBitmap* staticBitmap = NULL;
		wxPanel* panel = new wxPanel(hostDialog, (counter % 5) * panelWidth, (counter / 5) * panelHeight, panelWidth, panelHeight);
		wxButton* button = new wxButton(panel, wxID_ANY, wxT("Select"), wxPoint(0, 60), wxSize(panelWidth, 20));
		JoiningData* joiningData = NULL;

		// If the level is not known show the user an "unknown" thumbnail.
		if(NULL == wxGetApp().getConfiguration()->getLevels()->getLevel(iterator->getLevel()))
		{
			bitmapPath = path + wxT("unknown_thumbnails.bmp");
			// If the user disabled automatic download of unknown levels, he/she can not select this level, so set the button to disabled
			if(false == wxGetApp().getConfiguration()->getNetworkConfiguration()->downloadUnknownLevels())
			{
				button->Disable();
				// Inform the user about it in the status bar
				mStatusBar->SetStatusText(wxT("You have disabled automatic download of unknown levels. You can enable it in the Configuration menu."));
			}
		} // Else check if the server is free or not
		else if(1 == iterator->getFree())
			bitmapPath = path + iterator->getLevel() + pathSeparator + wxT("thumbnails.bmp");
		else
			bitmapPath = path + iterator->getLevel() + pathSeparator + wxT("not_free_thumbnails.bmp");
		bitmap = new wxBitmap(bitmapPath, wxBITMAP_TYPE_BMP);
		staticBitmap = new wxStaticBitmap(panel, wxID_ANY, *bitmap);
		button->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainFrame::onClicked), NULL, this);
		// Set the data needed for later use, when the user clicked on a button on the dialog
		button->SetToolTip(iterator->getLevel());
		joiningData = new JoiningData();
		joiningData->mData = iterator->getIpAddress();
		joiningData->mPort = iterator->getPort();
		joiningDatas->insert(std::pair<wxString, JoiningData*>(iterator->getLevel(), joiningData));
		button->SetClientData(hostDialog);
		staticBitmap->SetToolTip(iterator->getLevel());
		counter++;
	}
	// If there is no registered server, we need to show a special thumbnails
	if(0 == counter)
	{
		wxString bitmapPath = path + wxT("no_servers.bmp");
		wxBitmap* bitmap = new wxBitmap(bitmapPath, wxBITMAP_TYPE_BMP);
		wxPanel* panel = new wxPanel(hostDialog, 0, 0, panelWidth, panelHeight);
		wxStaticBitmap* staticBitmap = new wxStaticBitmap(panel, wxID_ANY, *bitmap);

		staticBitmap->SetToolTip(wxT("No server registered"));
	} // Else, calculate the dialog's size dynamically
	else if(5 == counter)
		dialogSize.y = panelHeight;
	else if(0 < (counter / 5))
		dialogSize.y = ((counter / 5) + 1) * panelHeight;
	dialogSize.y += 40;
	// Add the needed controllers for connecting by IP address and port
	ipPanel = new wxPanel(hostDialog, MAIN_FRAME_JOIN_IP_PANEL_ID, wxPoint(0, dialogSize.y - 40), wxSize(400, 40));
	okButton = new wxButton(ipPanel, MAIN_FRAME_JOIN_OK_BUTTON_ID, wxString(wxT("OK")), wxPoint(100, 20), defaultSize);
	cancelButton = new wxButton(ipPanel, MAIN_FRAME_JOIN_CANCEL_BUTTON_ID, wxString(wxT("Cancel")), wxPoint(200, 20), defaultSize);
	/*wxStaticText* ipText = */new wxStaticText(ipPanel, wxID_ANY, wxT("Ip "), wxPoint(0, 0), defaultSize);
	/*wxTextCtrl* ipTextCtrl = */new wxTextCtrl(ipPanel, MAIN_FRAME_JOIN_IP_TEXT_ID, wxT("127.0.0.1"), wxPoint(100, 0), defaultSize);
	/*wxStaticText* ipText = */new wxStaticText(ipPanel, wxID_ANY, wxT("Port "), wxPoint(200, 0), defaultSize);
	/*wxTextCtrl* ipTextCtrl = */new wxTextCtrl(ipPanel, MAIN_FRAME_JOIN_PORT_TEXT_ID, wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getNetworkConfiguration()->getPortNumber()), wxPoint(300, 0), defaultSize);
	okButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainFrame::onClicked), NULL, this);
	okButton->SetClientData(hostDialog);
	cancelButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainFrame::onClicked), NULL, this);
	cancelButton->SetClientData(hostDialog);
	// Set the data needed for later use when the user clicked on a button on the dialog
	hostDialog->SetClientSize(dialogSize);
	hostDialog->SetClientData(joiningDatas);
	hostDialog->Show(true);
}

void MainFrame::onMenuRestartClicked(wxCommandEvent& /*menuEvent*/)
{
	mMainPanel->restart();
}

void MainFrame::onMenuCloseClicked(wxCommandEvent& /*menuEvent*/)
{
	mMainPanel->finish();
}

void MainFrame::onMenuExitClicked(wxCommandEvent& /*menuEvent*/)
{
	mMainPanel->finish();
	this->Close(true);
}

void MainFrame::onMenuConfigureClicked(wxCommandEvent& /*menuEvent*/)
{
	wxString title(wxT("Configure"));
	wxDialog* dialog = new wxDialog(this, MAIN_FRAME_MENU_CONFIGURE_DIALOG_ID, title);
	wxPanel* panel = new wxPanel(dialog, wxID_ANY, wxPoint(0, 0), wxSize(500, 300));
	wxSize defaultSize(100, 20);
	std::vector<wxString> levelsVector = wxGetApp().getConfiguration()->getLevels()->getLevelNames();
	wxArrayString levelsArrayString;
	wxChoice* levelsChoice = NULL;
	wxCheckBox* proxyCheckBox = NULL;
	wxCheckBox* freeServersCheckBox = NULL;
	wxCheckBox* downloadUnknownLevelsCheckBox = NULL;
	wxCheckBox* uploadLevelsCheckBox = NULL;
	wxCheckBox* registerServerCheckBox = NULL;
	wxButton* okButton = new wxButton(panel, MAIN_FRAME_CONFIGURE_OK_BUTTON_ID, wxString(wxT("OK")), wxPoint(100, 380), wxSize(100, 20));
	wxButton* cancelButton = new wxButton(panel, MAIN_FRAME_CONFIGURE_CANCEL_BUTTON_ID, wxString(wxT("Cancel")), wxPoint(300, 380), wxSize(100, 20));

	// Ugly GUI builder code to show the configure dialog to the user
	for(unsigned int i = 0; i < levelsVector.size(); i++)
		levelsArrayString.Add(levelsVector[i]);
	levelsChoice = new wxChoice(panel, MAIN_FRAME_CONFIGURE_LEVEL_CHOICE_ID, wxPoint(10, 240), defaultSize, levelsArrayString);
	levelsChoice->SetSelection(0);
	/*wxStaticText* logoText = */new wxStaticText(panel, wxID_ANY, wxT("Logo "), wxPoint(10, 10), defaultSize);
	/*wxTextCtrl* logoTextCtrl = */new wxTextCtrl(panel, MAIN_FRAME_CONFIGURE_LOGO_TEXT_ID, wxGetApp().getConfiguration()->getLogoPath(), wxPoint(120, 10), defaultSize);
	/*wxStaticText* dotSizeText = */new wxStaticText(panel, wxID_ANY, wxT("Dot size "), wxPoint(230, 10), defaultSize);
	/*wxTextCtrl* dotSizeTextCtrl = */new wxTextCtrl(panel, MAIN_FRAME_CONFIGURE_DOT_SIZE_TEXT_ID, wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getDotSize()), wxPoint(340, 10), defaultSize);
	/*wxStaticBox* networkBox = */new wxStaticBox(panel, wxID_ANY, wxT("Network"), wxPoint(0, 30), wxSize(500, 180));
	/*wxStaticText* portText = */new wxStaticText(panel, wxID_ANY, wxT("Port "), wxPoint(10, 50), defaultSize);
	/*wxTextCtrl* portTextCtrl = */new wxTextCtrl(panel, MAIN_FRAME_CONFIGURE_PORT_NUMBER_TEXT_ID, wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getNetworkConfiguration()->getPortNumber()), wxPoint(120, 50), defaultSize);
	/*wxStaticText* frequencyText = */new wxStaticText(panel, wxID_ANY, wxT("Frequency "), wxPoint(230, 50), defaultSize);
	/*wxTextCtrl* frequencyTextCtrl = */new wxTextCtrl(panel, MAIN_FRAME_CONFIGURE_FREQUENCY_TEXT_ID, wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getNetworkConfiguration()->getFrequency()), wxPoint(340, 50), defaultSize);
	freeServersCheckBox = new wxCheckBox(panel, MAIN_FRAME_CONFIGURE_FREE_SERVERS_CHECK_BOX_ID, wxT("Only free servers"), wxPoint(10, 70), wxSize(150, 20));
	registerServerCheckBox = new wxCheckBox(panel, MAIN_FRAME_CONFIGURE_REGISTER_SERVER_CHECK_BOX_ID, wxT("Register server"), wxPoint(340, 70), wxSize(150, 20));
	downloadUnknownLevelsCheckBox = new wxCheckBox(panel, MAIN_FRAME_CONFIGURE_DOWNLOAD_UNKNOWN_LEVELS_CHECK_BOX_ID, wxT("Download unknown levels"), wxPoint(10, 90), wxSize(150, 20));
	uploadLevelsCheckBox = new wxCheckBox(panel, MAIN_FRAME_CONFIGURE_UPLOAD_LEVELS_CHECK_BOX_ID, wxT("Upload levels"), wxPoint(340, 90), wxSize(150, 20));
	freeServersCheckBox->SetValue(wxGetApp().getConfiguration()->getNetworkConfiguration()->fetchOnlyFreeServers());
	registerServerCheckBox->SetValue(wxGetApp().getConfiguration()->getNetworkConfiguration()->registerServer());
	downloadUnknownLevelsCheckBox->SetValue(wxGetApp().getConfiguration()->getNetworkConfiguration()->downloadUnknownLevels());
	uploadLevelsCheckBox->SetValue(wxGetApp().getConfiguration()->getNetworkConfiguration()->uploadLevels());
	/*wxStaticBox* proxyBox = */new wxStaticBox(panel, wxID_ANY, wxT("Proxy"), wxPoint(10, 120), wxSize(480, 80));
	proxyCheckBox = new wxCheckBox(panel, MAIN_FRAME_CONFIGURE_PROXY_CHECK_BOX_ID, wxT("Use proxy"), wxPoint(20, 140), defaultSize);
	/*wxStaticText* proxyHostText = */new wxStaticText(panel, wxID_ANY, wxT("Host "), wxPoint(20, 170), defaultSize);
	wxTextCtrl* proxyHostTextCtrl = new wxTextCtrl(panel, MAIN_FRAME_CONFIGURE_PROXY_HOST_TEXT_ID, wxGetApp().getConfiguration()->getNetworkConfiguration()->getProxyConfiguration()->getProxyAddress()->getHost(), wxPoint(120, 170), defaultSize);
	/*wxStaticText* proxyPortText = */new wxStaticText(panel, wxID_ANY, wxT("Port "), wxPoint(240, 170), defaultSize);
	wxTextCtrl* proxyPortTextCtrl = new wxTextCtrl(panel, MAIN_FRAME_CONFIGURE_PROXY_PORT_TEXT_ID, wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getNetworkConfiguration()->getProxyConfiguration()->getProxyAddress()->getPort()), wxPoint(340, 170), defaultSize);
	if(true == wxGetApp().getConfiguration()->getNetworkConfiguration()->getProxyConfiguration()->useProxy())
	{
		proxyCheckBox->SetValue(true);
		proxyHostTextCtrl->Enable(true);
		proxyPortTextCtrl->Enable(true);
	}
	else
	{
		proxyCheckBox->SetValue(false);
		proxyHostTextCtrl->Enable(false);
		proxyPortTextCtrl->Enable(false);
	}

	/*wxStaticBox* levelBox = */new wxStaticBox(panel, wxID_ANY, wxT("Level"), wxPoint(0, 220), wxSize(500, 150));
	/*wxStaticText* vehicleAText = */new wxStaticText(panel, wxID_ANY, wxGetApp().getConfiguration()->getLevels()->getLevel(levelsChoice->GetString(0))->getVehicleA()->getName(), wxPoint(10, 270), defaultSize);
	/*wxStaticText* vehicleAText = */new wxStaticText(panel, wxID_ANY, wxT("X"), wxPoint(10, 290), defaultSize);
	/*wxStaticText* vehicleAText = */new wxStaticText(panel, wxID_ANY, wxT("Y"), wxPoint(10, 310), defaultSize);
	/*wxTextCtrl* vehicleAXTextCtrl = */new wxTextCtrl(panel, MAIN_FRAME_CONFIGURE_VEHICLE_A_X_TEXT_ID, wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getLevels()->getLevel(levelsChoice->GetString(0))->getVehicleA()->getPosition().x), wxPoint(120, 290), wxSize(70, 20));
	/*wxTextCtrl* vehicleAXTextCtrl = */new wxTextCtrl(panel, MAIN_FRAME_CONFIGURE_VEHICLE_A_Y_TEXT_ID, wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getLevels()->getLevel(levelsChoice->GetString(0))->getVehicleA()->getPosition().y), wxPoint(120, 310), wxSize(70, 20));
	/*wxStaticText* vehicleAText = */new wxStaticText(panel, wxID_ANY, wxGetApp().getConfiguration()->getLevels()->getLevel(levelsChoice->GetString(0))->getVehicleB()->getName(), wxPoint(230, 250), defaultSize);
	/*wxStaticText* vehicleAText = */new wxStaticText(panel, wxID_ANY, wxT("X"), wxPoint(230, 290), defaultSize);
	/*wxStaticText* vehicleAText = */new wxStaticText(panel, wxID_ANY, wxT("Y"), wxPoint(230, 310), defaultSize);
	/*wxTextCtrl* vehicleAXTextCtrl = */new wxTextCtrl(panel, MAIN_FRAME_CONFIGURE_VEHICLE_B_X_TEXT_ID, wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getLevels()->getLevel(levelsChoice->GetString(0))->getVehicleB()->getPosition().x), wxPoint(340, 290), wxSize(70, 20));
	/*wxTextCtrl* vehicleAXTextCtrl = */new wxTextCtrl(panel, MAIN_FRAME_CONFIGURE_VEHICLE_B_Y_TEXT_ID, wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getLevels()->getLevel(levelsChoice->GetString(0))->getVehicleB()->getPosition().y), wxPoint(340, 310), wxSize(70, 20));
	levelsChoice->Connect(wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(MainFrame::onLevelSelected), NULL, this);
	levelsChoice->SetClientData(dialog);
	proxyCheckBox->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainFrame::onProxyChecked), NULL, this);
	proxyCheckBox->SetClientData(dialog);
	okButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainFrame::onClicked), NULL, this);
	okButton->SetClientData(dialog);
	cancelButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainFrame::onClicked), NULL, this);
	cancelButton->SetClientData(dialog);
	dialog->SetClientSize(wxSize(500, 400));
	dialog->Show(true);
}

void MainFrame::onMenuMessagingClicked(wxCommandEvent& /*menuEvent*/)
{
	this->createMessagingFrame();
}

void MainFrame::showMessageDialog(const wxString& message, DialogMessageType messageType)
{
	wxMessageDialog* dialog = NULL;

	switch(messageType)
	{
		case SERVER_ERROR:
			dialog = new wxMessageDialog(this, message, wxT("Server error"), wxOK | wxICON_ERROR);
			break;
		case CLIENT_ERROR:
			dialog = new wxMessageDialog(this, message, wxT("Client error"), wxOK | wxICON_ERROR);
			break;
		case USER_ERROR:
			dialog = new wxMessageDialog(this, message, wxT("Usage error"), wxOK | wxICON_ERROR);
			break;
		case GAME_START:
			dialog = new wxMessageDialog(this, message, wxT("Game started"), wxOK | wxICON_INFORMATION);
			break;
		case GAME_FINISH:
			dialog = new wxMessageDialog(this, message, wxT("Game finished"), wxOK | wxICON_INFORMATION);
			break;
		case INVALID:
			wxASSERT_MSG(false, wxT("INVALID message type received!"));
			break;
		default:
			wxASSERT_MSG(false, wxT("Unknown message type received!"));
			break;
	}
	dialog->ShowModal();
}

void MainFrame::onClicked(wxCommandEvent& commandEvent)
{
	wxWindowBase* eventSource = static_cast<wxWindowBase*>(commandEvent.GetEventObject());
	wxDialog* dialog = static_cast<wxDialog*>(eventSource->GetClientData());
	const wxWindowList* dialogChildren = NULL;
	const wxWindowList* panelChildren = NULL;
	wxWindowListNode* child = NULL;
	wxTextCtrl* textCtrl = NULL;
	wxChoice* choice = NULL;
	wxString selectedLevel;
	wxPoint vehicleAPosition = WxUtils::INVALID_POINT;
	wxPoint vehicleBPosition = WxUtils::INVALID_POINT;
	int frequency = -1;
	int dotSize = -1;
	wxString host;
	int portNumber = 0;
	bool closeDialog = true;
	bool isConfiguration = false;
	std::map<wxString, JoiningData*>* joiningDatas = NULL;

	if(NULL == dialog)
		return;
	// Switch between the different possible event sources
	switch(eventSource->GetId())
	{
		case MAIN_FRAME_JOIN_OK_BUTTON_ID: // OK button on the "Join" dialog
			// First find the ip panel
			dialogChildren = &(dialog->GetChildren());
			child = dialogChildren->GetFirst();
			while(NULL != child)
			{
				if(MAIN_FRAME_JOIN_IP_PANEL_ID == child->GetData()->GetId())
				{
					// Then find the given IP address and port number
					panelChildren = &(child->GetData()->GetChildren());
					child = panelChildren->GetFirst();
					while(NULL != child)
					{
						switch(child->GetData()->GetId())
						{
							case MAIN_FRAME_JOIN_IP_TEXT_ID:
								host = static_cast<wxTextCtrl*>(child->GetData())->GetValue();
								break;
							case MAIN_FRAME_JOIN_PORT_TEXT_ID:
								portNumber = wxAtoi(static_cast<wxTextCtrl*>(child->GetData())->GetValue());
								break;
							default:
								break;
						}
						child = child->GetNext();
					}
					// We found the needed data we can start the client
					break;
				}
				child = child->GetNext();
			}
			mMainPanel->joinNew(host, portNumber);
			break;
		case MAIN_FRAME_JOIN_CANCEL_BUTTON_ID: // Cancel button on the "Join" dialog
			// Nothing to do, since the dialog is already closed
			break;
		case MAIN_FRAME_HOST_CANCEL_BUTTON_ID: // Cancel button on the "Host" dialog
			// Nothing to do, since the dialog is already closed
			break;
		case MAIN_FRAME_CONFIGURE_OK_BUTTON_ID: // OK button on the "Configure" dialog
			// Set it to true, since we are most probably changing configuration
			isConfiguration = true;
			// Find the wxChoice
			dialogChildren = &(dialog->GetChildren());
			panelChildren = &(dialogChildren->GetFirst()->GetData()->GetChildren());
			child = panelChildren->GetFirst();
			while(NULL != child)
			{
				if(MAIN_FRAME_CONFIGURE_LEVEL_CHOICE_ID == child->GetData()->GetId())
				{
					choice = static_cast<wxChoice*>(child->GetData());
					break;
				}
				child = child->GetNext();
			}
			selectedLevel = choice->GetString(choice->GetCurrentSelection());
			child = panelChildren->GetFirst();
			while(NULL != child)
			{
				textCtrl = static_cast<wxTextCtrl*>(child->GetData());
				// Set every values from the text boxes
				switch(child->GetData()->GetId())
				{
					case MAIN_FRAME_CONFIGURE_LOGO_TEXT_ID:
						wxGetApp().getConfiguration()->setLogoPath(textCtrl->GetValue());
						break;
					case MAIN_FRAME_CONFIGURE_DOT_SIZE_TEXT_ID:
						dotSize = wxAtoi(textCtrl->GetValue());
						break;
					case MAIN_FRAME_CONFIGURE_PORT_NUMBER_TEXT_ID:
						wxGetApp().getConfiguration()->getNetworkConfiguration()->setPortNumber(wxAtoi(textCtrl->GetValue()));
						break;
					case MAIN_FRAME_CONFIGURE_FREQUENCY_TEXT_ID:
						frequency = wxAtoi(textCtrl->GetValue());
						break;
					case MAIN_FRAME_CONFIGURE_FREE_SERVERS_CHECK_BOX_ID:
						wxGetApp().getConfiguration()->getNetworkConfiguration()->fetchOnlyFreeServers(static_cast<wxCheckBox*>(child->GetData())->IsChecked());
						break;
					case MAIN_FRAME_CONFIGURE_DOWNLOAD_UNKNOWN_LEVELS_CHECK_BOX_ID:
						wxGetApp().getConfiguration()->getNetworkConfiguration()->downloadUnknownLevels(static_cast<wxCheckBox*>(child->GetData())->IsChecked());
						break;
					case MAIN_FRAME_CONFIGURE_UPLOAD_LEVELS_CHECK_BOX_ID:
						wxGetApp().getConfiguration()->getNetworkConfiguration()->uploadLevels(static_cast<wxCheckBox*>(child->GetData())->IsChecked());
						break;
					case MAIN_FRAME_CONFIGURE_REGISTER_SERVER_CHECK_BOX_ID:
						wxGetApp().getConfiguration()->getNetworkConfiguration()->registerServer(static_cast<wxCheckBox*>(child->GetData())->IsChecked());
						break;
					case MAIN_FRAME_CONFIGURE_PROXY_CHECK_BOX_ID:
						wxGetApp().getConfiguration()->getNetworkConfiguration()->getProxyConfiguration()->setUseProxy(static_cast<wxCheckBox*>(child->GetData())->IsChecked());
						break;
					case MAIN_FRAME_CONFIGURE_PROXY_HOST_TEXT_ID:
						wxGetApp().getConfiguration()->getNetworkConfiguration()->getProxyConfiguration()->getProxyAddress()->setHost(textCtrl->GetValue());
						break;
					case MAIN_FRAME_CONFIGURE_PROXY_PORT_TEXT_ID:
						wxGetApp().getConfiguration()->getNetworkConfiguration()->getProxyConfiguration()->getProxyAddress()->setPort(wxAtoi(textCtrl->GetValue()));
						break;
					case MAIN_FRAME_CONFIGURE_VEHICLE_A_X_TEXT_ID:
						vehicleAPosition.x = wxAtoi(textCtrl->GetValue());
						break;
					case MAIN_FRAME_CONFIGURE_VEHICLE_A_Y_TEXT_ID:
						vehicleAPosition.y = wxAtoi(textCtrl->GetValue());
						break;
					case MAIN_FRAME_CONFIGURE_VEHICLE_B_X_TEXT_ID:
						vehicleBPosition.x = wxAtoi(textCtrl->GetValue());
						break;
					case MAIN_FRAME_CONFIGURE_VEHICLE_B_Y_TEXT_ID:
						vehicleBPosition.y = wxAtoi(textCtrl->GetValue());
						break;
					default:
						break;
				}
				child = child->GetNext();
			}
			// Sanity checks
			if(dotSize < 5)
			{
				this->showMessageDialog(wxT("The minimum dot size is 5 pixels."), MainFrame::USER_ERROR);
				// Do not close the dialog, since the user has to correct the values
				closeDialog = false;
			}
			else
				wxGetApp().getConfiguration()->setDotSize(dotSize);
			if(frequency < 0)
			{
				this->showMessageDialog(wxT("Frequency must be a positive number."), MainFrame::USER_ERROR);
				// Do not close the dialog, since the user has to correct the values
				closeDialog = false;
			}
			else
				wxGetApp().getConfiguration()->getNetworkConfiguration()->setFrequency(frequency);
			if(vehicleAPosition.x != vehicleBPosition.x && vehicleAPosition.y != vehicleBPosition.y)
			{
				this->showMessageDialog(wxT("Vehicles must be in one line - horizontally or vertically"), MainFrame::USER_ERROR);
				// Do not close the dialog, since the user has to correct the values
				closeDialog = false;
			}
			else
			{
				wxGetApp().getConfiguration()->getLevels()->getLevel(selectedLevel)->getVehicleA()->setPosition(vehicleAPosition);
				wxGetApp().getConfiguration()->getLevels()->getLevel(selectedLevel)->getVehicleB()->setPosition(vehicleBPosition);
			}
			break;
		case MAIN_FRAME_CONFIGURE_CANCEL_BUTTON_ID: // Cancel button on the "Configure" dialog
			// Now the dialog is closed so there is nothing to do
			break;
		default: // Mainly the OK button on the "Host" or "Join" dialog
			if(true == mIsServerStarting)
			{
				// This is the case, when a server needs to be started
				if(false == mMainPanel->hostNew(eventSource->GetToolTip()->GetTip()))
					this->showMessageDialog(wxT("Error during start procedure"), SERVER_ERROR);
			}
			else
			{
				// This is the case, when a client needs to be started
				joiningDatas = static_cast<std::map<wxString, JoiningData*>*>(dialog->GetClientData());
				host = joiningDatas->at(eventSource->GetToolTip()->GetTip())->mData;
				portNumber = joiningDatas->at(eventSource->GetToolTip()->GetTip())->mPort;
				for(std::map<wxString, JoiningData*>::iterator iterator = joiningDatas->begin(); iterator != joiningDatas->end(); iterator++)
				{
					delete iterator->second;
					iterator->second = NULL;
				}
				joiningDatas->clear();
				delete joiningDatas;
				if(false == mMainPanel->joinNew(host, portNumber))
					this->showMessageDialog(wxT("Error during start procedure"), CLIENT_ERROR);
			}
			break;
	}
	// Close the dialog if needed
	if(true == closeDialog)
	{
		dialog->Close(true);
		dialog->Destroy();
		// If the configuration changed inform the MainPanel (and the GameController) about it
		if(true == isConfiguration)
			mMainPanel->configurationChange();
	}
}

void MainFrame::onLevelSelected(wxCommandEvent& commandEvent)
{
	wxChoice* eventSource = static_cast<wxChoice*>(commandEvent.GetEventObject());
	wxDialog* dialog = static_cast<wxDialog*>(eventSource->GetClientData());
	unsigned int selection = eventSource->GetCurrentSelection();
	wxString selectedLevel = eventSource->GetString(selection);
	const wxWindowList* dialogChildren = NULL;
	const wxWindowList* panelChildren = NULL;
	wxWindowListNode* child = NULL;
	wxTextCtrl* vehicleAX = NULL;
	wxTextCtrl* vehicleAY = NULL;
	wxTextCtrl* vehicleBX = NULL;
	wxTextCtrl* vehicleBY = NULL;

	if(NULL == dialog)
		return;
	dialogChildren = &(dialog->GetChildren());
	panelChildren = &(dialogChildren->GetFirst()->GetData()->GetChildren());
	child = panelChildren->GetFirst();
	while(child)
	{
		switch(child->GetData()->GetId())
		{
			case MAIN_FRAME_CONFIGURE_VEHICLE_A_X_TEXT_ID:
				vehicleAX = static_cast<wxTextCtrl*>(child->GetData());
				break;
			case MAIN_FRAME_CONFIGURE_VEHICLE_A_Y_TEXT_ID:
				vehicleAY = static_cast<wxTextCtrl*>(child->GetData());
				break;
			case MAIN_FRAME_CONFIGURE_VEHICLE_B_X_TEXT_ID:
				vehicleBX = static_cast<wxTextCtrl*>(child->GetData());
				break;
			case MAIN_FRAME_CONFIGURE_VEHICLE_B_Y_TEXT_ID:
				vehicleBY = static_cast<wxTextCtrl*>(child->GetData());
				break;
			default:
				break;
		}
		child = child->GetNext();
	}
	vehicleAX->SetValue(wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getLevels()->getLevel(selectedLevel)->getVehicleA()->getPosition().x));
	vehicleAY->SetValue(wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getLevels()->getLevel(selectedLevel)->getVehicleA()->getPosition().y));
	vehicleBX->SetValue(wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getLevels()->getLevel(selectedLevel)->getVehicleB()->getPosition().x));
	vehicleBY->SetValue(wxString::Format(wxT("%d"), wxGetApp().getConfiguration()->getLevels()->getLevel(selectedLevel)->getVehicleB()->getPosition().y));
}

void MainFrame::onProxyChecked(wxCommandEvent& commandEvent)
{
	wxCheckBox* checkBox = static_cast<wxCheckBox*>(commandEvent.GetEventObject());
	wxDialog* dialog = static_cast<wxDialog*>(checkBox->GetClientData());
	const wxWindowList* dialogChildren = NULL;
	const wxWindowList* panelChildren = NULL;
	wxWindowListNode* child = NULL;
	wxTextCtrl* hostTextCtrl = NULL;
	wxTextCtrl* portTextCtrl = NULL;

	if(NULL == dialog)
		return;
	dialogChildren = &(dialog->GetChildren());
	panelChildren = &(dialogChildren->GetFirst()->GetData()->GetChildren());
	child = panelChildren->GetFirst();
	while(child)
	{
		switch(child->GetData()->GetId())
		{
			case MAIN_FRAME_CONFIGURE_PROXY_HOST_TEXT_ID:
				hostTextCtrl = static_cast<wxTextCtrl*>(child->GetData());
				break;
			case MAIN_FRAME_CONFIGURE_PROXY_PORT_TEXT_ID:
				portTextCtrl = static_cast<wxTextCtrl*>(child->GetData());
				break;
			default:
				break;
		}
		child = child->GetNext();
	}
	wxASSERT_MSG(hostTextCtrl != NULL, wxT("Could not find Host text control"));
	wxASSERT_MSG(portTextCtrl != NULL, wxT("Could not find Port text control"));
	if(true == checkBox->IsChecked())
	{
		hostTextCtrl->Enable(true);
		portTextCtrl->Enable(true);
	}
	else
	{
		hostTextCtrl->Enable(false);
		portTextCtrl->Enable(false);
	}
}

void MainFrame::onMainPanelClientSizeChange(const wxSize& newClientSize)
{
	this->wxFrame::SetClientSize(newClientSize.x, newClientSize.y);
}

void MainFrame::createMessagingFrame()
{
	wxASSERT_MSG(NULL == mMessagingFrame, wxT("Messaging frame is already created!"));
	mMessagingFrame = new MessagingFrame(wxT("Messaging"));
}
